{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/jd4615/miniconda3/envs/insightface/lib/python2.7/site-packages/sklearn/utils/fixes.py:313: FutureWarning: numpy not_equal will not check object identity in the future. The comparison did not return the same result as suggested by the identity (`is`)) and will change.\n",
      "  _nan_object_mask = _nan_object_array != _nan_object_array\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import numpy as np\n",
    "import cPickle\n",
    "from sklearn.metrics import roc_curve, auc\n",
    "import matplotlib.pyplot as plt\n",
    "import timeit\n",
    "import sklearn\n",
    "import cv2\n",
    "import sys\n",
    "import glob\n",
    "sys.path.append('./recognition')\n",
    "from embedding import Embedding\n",
    "from menpo.visualize import print_progress\n",
    "from menpo.visualize.viewmatplotlib import sample_colours_from_colourmap\n",
    "from prettytable import PrettyTable\n",
    "from pathlib import Path\n",
    "import warnings \n",
    "warnings.filterwarnings(\"ignore\")  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def read_template_media_list(path):\n",
    "    ijb_meta = np.loadtxt(path, dtype=str)\n",
    "    templates = ijb_meta[:,1].astype(np.int)\n",
    "    medias = ijb_meta[:,2].astype(np.int)\n",
    "    return templates, medias"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def read_template_pair_list(path):\n",
    "    pairs = np.loadtxt(path, dtype=str)\n",
    "    t1 = pairs[:,0].astype(np.int)\n",
    "    t2 = pairs[:,1].astype(np.int)\n",
    "    label = pairs[:,2].astype(np.int)\n",
    "    return t1, t2, label"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def read_image_feature(path):\n",
    "    with open(path, 'rb') as fid:\n",
    "        img_feats = cPickle.load(fid)\n",
    "    return img_feats"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_image_feature(img_path, img_list_path, model_path, gpu_id):\n",
    "    img_list = open(img_list_path)\n",
    "    embedding = Embedding(model_path, 0, gpu_id)\n",
    "    files = img_list.readlines()\n",
    "    img_feats = []\n",
    "    faceness_scores = []\n",
    "    for img_index, each_line in enumerate(print_progress(files)):\n",
    "        name_lmk_score = each_line.strip().split(' ')\n",
    "        img_name = os.path.join(img_path, name_lmk_score[0])\n",
    "        img = cv2.imread(img_name)\n",
    "        lmk = np.array([float(x) for x in name_lmk_score[1:-1]], dtype=np.float32)\n",
    "        lmk = lmk.reshape( (5,2) )\n",
    "        img_feats.append(embedding.get(img,lmk))\n",
    "        faceness_scores.append(name_lmk_score[-1])\n",
    "    img_feats = np.array(img_feats).astype(np.float32)\n",
    "    faceness_scores = np.array(faceness_scores).astype(np.float32)\n",
    "    return img_feats, faceness_scores"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def image2template_feature(img_feats = None, templates = None, medias = None):\n",
    "    # ==========================================================\n",
    "    # 1. face image feature l2 normalization. img_feats:[number_image x feats_dim]\n",
    "    # 2. compute media feature.\n",
    "    # 3. compute template feature.\n",
    "    # ==========================================================    \n",
    "    unique_templates = np.unique(templates)\n",
    "    template_feats = np.zeros((len(unique_templates), img_feats.shape[1]))\n",
    "\n",
    "    for count_template, uqt in enumerate(unique_templates):\n",
    "        (ind_t,) = np.where(templates == uqt)\n",
    "        face_norm_feats = img_feats[ind_t]\n",
    "        face_medias = medias[ind_t]\n",
    "        unique_medias, unique_media_counts = np.unique(face_medias, return_counts=True)\n",
    "        media_norm_feats = []\n",
    "        for u,ct in zip(unique_medias, unique_media_counts):\n",
    "            (ind_m,) = np.where(face_medias == u)\n",
    "            if ct == 1:\n",
    "                media_norm_feats += [face_norm_feats[ind_m]]\n",
    "            else: # image features from the same video will be aggregated into one feature\n",
    "                media_norm_feats += [np.mean(face_norm_feats[ind_m], 0, keepdims=True)]\n",
    "        media_norm_feats = np.array(media_norm_feats)\n",
    "        # media_norm_feats = media_norm_feats / np.sqrt(np.sum(media_norm_feats ** 2, -1, keepdims=True))\n",
    "        template_feats[count_template] = np.sum(media_norm_feats, 0)\n",
    "        if count_template % 2000 == 0: \n",
    "            print('Finish Calculating {} template features.'.format(count_template))\n",
    "    template_norm_feats = template_feats / np.sqrt(np.sum(template_feats ** 2, -1, keepdims=True))\n",
    "    return template_norm_feats, unique_templates"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def verification(template_norm_feats = None, unique_templates = None, p1 = None, p2 = None):\n",
    "    # ==========================================================\n",
    "    #         Compute set-to-set Similarity Score.\n",
    "    # ==========================================================\n",
    "    template2id = np.zeros((max(unique_templates)+1,1),dtype=int)\n",
    "    for count_template, uqt in enumerate(unique_templates):\n",
    "        template2id[uqt] = count_template\n",
    "    \n",
    "    score = np.zeros((len(p1),))   # save cosine distance between pairs \n",
    "\n",
    "    total_pairs = np.array(range(len(p1)))\n",
    "    batchsize = 100000 # small batchsize instead of all pairs in one batch due to the memory limiation\n",
    "    sublists = [total_pairs[i:i + batchsize] for i in range(0, len(p1), batchsize)]\n",
    "    total_sublists = len(sublists)\n",
    "    for c, s in enumerate(sublists):\n",
    "        feat1 = template_norm_feats[template2id[p1[s]]]\n",
    "        feat2 = template_norm_feats[template2id[p2[s]]]\n",
    "        similarity_score = np.sum(feat1 * feat2, -1)\n",
    "        score[s] = similarity_score.flatten()\n",
    "        if c % 10 == 0:\n",
    "            print('Finish {}/{} pairs.'.format(c, total_sublists))\n",
    "    return score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def read_score(path):\n",
    "    with open(path, 'rb') as fid:\n",
    "        img_feats = cPickle.load(fid)\n",
    "    return img_feats"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Step1: Load Meta Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time: 0.83 s. \n"
     ]
    }
   ],
   "source": [
    "# =============================================================\n",
    "# load image and template relationships for template feature embedding\n",
    "# tid --> template id,  mid --> media id \n",
    "# format:\n",
    "#           image_name tid mid\n",
    "# =============================================================\n",
    "start = timeit.default_timer()\n",
    "templates, medias = read_template_media_list(os.path.join('IJBB/meta', 'ijbb_face_tid_mid.txt'))\n",
    "stop = timeit.default_timer()\n",
    "print('Time: %.2f s. ' % (stop - start))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Time: 31.88 s. \n"
     ]
    }
   ],
   "source": [
    "# =============================================================\n",
    "# load template pairs for template-to-template verification\n",
    "# tid : template id,  label : 1/0\n",
    "# format:\n",
    "#           tid_1 tid_2 label\n",
    "# =============================================================\n",
    "start = timeit.default_timer()\n",
    "p1, p2, label = read_template_pair_list(os.path.join('IJBB/meta', 'ijbb_template_pair_label.txt'))\n",
    "stop = timeit.default_timer()\n",
    "print('Time: %.2f s. ' % (stop - start))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Step 2: Get Image Features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('loading', './pretrained_models/MS1MV2-ResNet100-Arcface/model', 0)\n",
      "[====================] 100% (227630/227630) - done.                             \n",
      "Time: 3279.69 s. \n",
      "Feature Shape: (227630 , 1024) .\n"
     ]
    }
   ],
   "source": [
    "# =============================================================\n",
    "# load image features \n",
    "# format:\n",
    "#           img_feats: [image_num x feats_dim] (227630, 512)\n",
    "# =============================================================\n",
    "start = timeit.default_timer()\n",
    "#img_feats = read_image_feature('./MS1MV2/IJBB_MS1MV2_r100_arcface.pkl')\n",
    "img_path = './IJBB/loose_crop'\n",
    "img_list_path = './IJBB/meta/ijbb_name_5pts_score.txt'\n",
    "model_path = './pretrained_models/MS1MV2-ResNet100-Arcface/model'\n",
    "gpu_id = 1\n",
    "img_feats, faceness_scores = get_image_feature(img_path, img_list_path, model_path, gpu_id)\n",
    "stop = timeit.default_timer()\n",
    "print('Time: %.2f s. ' % (stop - start))\n",
    "print('Feature Shape: ({} , {}) .'.format(img_feats.shape[0], img_feats.shape[1]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Step3: Get Template Features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Finish Calculating 0 template features.\n",
      "Finish Calculating 2000 template features.\n",
      "Finish Calculating 4000 template features.\n",
      "Finish Calculating 6000 template features.\n",
      "Finish Calculating 8000 template features.\n",
      "Finish Calculating 10000 template features.\n",
      "Finish Calculating 12000 template features.\n",
      "Time: 3.65 s. \n"
     ]
    }
   ],
   "source": [
    "# =============================================================\n",
    "# compute template features from image features.\n",
    "# =============================================================\n",
    "start = timeit.default_timer()\n",
    "# ========================================================== \n",
    "# Norm feature before aggregation into template feature?\n",
    "# Feature norm from embedding network and faceness score are able to decrease weights for noise samples (not face).\n",
    "# ========================================================== \n",
    "# 1. FaceScore （Feature Norm）\n",
    "# 2. FaceScore （Detector）\n",
    "\n",
    "use_norm_score = True # if True, TestMode(N1)  \n",
    "use_detector_score = True # if True, TestMode(D1)\n",
    "use_flip_test = True # if True, TestMode(F2)\n",
    "\n",
    "if use_flip_test:\n",
    "    # concat --- F1\n",
    "    # img_input_feats = img_feats \n",
    "    # add --- F2\n",
    "    img_input_feats = img_feats[:,0:img_feats.shape[1]/2] + img_feats[:,img_feats.shape[1]/2:]\n",
    "else:\n",
    "    img_input_feats = img_feats[:,0:img_feats.shape[1]/2]\n",
    "    \n",
    "if use_norm_score:\n",
    "    img_input_feats = img_input_feats\n",
    "else:\n",
    "    # normalise features to remove norm information\n",
    "    img_input_feats = img_input_feats / np.sqrt(np.sum(img_input_feats ** 2, -1, keepdims=True))    \n",
    "    \n",
    "if use_detector_score:\n",
    "    img_input_feats = img_input_feats * np.matlib.repmat(faceness_scores[:,np.newaxis], 1, img_input_feats.shape[1])\n",
    "else:\n",
    "    img_input_feats = img_input_feats\n",
    "\n",
    "template_norm_feats, unique_templates = image2template_feature(img_input_feats, templates, medias)\n",
    "stop = timeit.default_timer()\n",
    "print('Time: %.2f s. ' % (stop - start))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Step 4: Get Template Similarity Scores"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Finish 0/81 pairs.\n",
      "Finish 10/81 pairs.\n",
      "Finish 20/81 pairs.\n",
      "Finish 30/81 pairs.\n",
      "Finish 40/81 pairs.\n",
      "Finish 50/81 pairs.\n",
      "Finish 60/81 pairs.\n",
      "Finish 70/81 pairs.\n",
      "Finish 80/81 pairs.\n",
      "Time: 77.30 s. \n"
     ]
    }
   ],
   "source": [
    "# =============================================================\n",
    "# compute verification scores between template pairs.\n",
    "# =============================================================\n",
    "start = timeit.default_timer()\n",
    "score = verification(template_norm_feats, unique_templates, p1, p2)\n",
    "stop = timeit.default_timer()\n",
    "print('Time: %.2f s. ' % (stop - start))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [],
   "source": [
    "score_save_name = './IJBB/result/MS1MV2-ResNet100-ArcFace-TestMode(N1D1F2).npy'\n",
    "np.save(score_save_name, score)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Step 5: Get ROC Curves and TPR@FPR Table"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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9tlnufDCCxvZfscdd/Dzn/+8SZtSU1OZNGnSET/r6enpPPLIIyxZsoTy8nJEhPPOO4+srKw26zdt2jS6d+/eJH3QoEHs27ePgwcPNjnXXFsWLVrE7373O3bs2MG+ffvaVPcvfvEL7r//fnr37g1Evts33nhjm21vji1btjBx4kSSkpJwuVxMnz49+nT1+eefM2nSJABmzJjB888/3+R6y7JISYnc3gKBAMFgMDrY/H//938sWLAgetyrV9Meh0WLFnHNNdcclc2qSigUoqamBpfLxRNPPMGll17a5Glt7ty5PP1054gv25aNnJYCZ4rIIOCvwMvA34GL42lYS1RUVCSiWgBKy31s2lxIpq86YTY0ZPny5cyaNSvu9Xzznb+3e5kPT/mP4y7jk08+4cUXX+S9996jurqaO+64g8WLFzNo0CAOHTrExx9/DMTm8i9cuJA//OEPjR7vZ8yYwQ033IBt2zzzzDM89thj/PKXvwQiN8gtW7awceNGDh48yJlnnsnUqVNZuXIlX3zxBZs3b2bv3r0MHz6cb33rW/j9fm699VZeeuklevTowdNPP81PfvITHnnkEd59912+9rWvNbJ/ypQpPPfcc6xevRqnsy1fxaZkZGTQv39/tm/fztixY4FId0tzXHXVVSQlJQGRrpAjdcmNGTOG9957r8kEjMPbUlhYSElJCWPHjuWKK65gyZIl3HrrrUe0fdOmTVGbW+PJJ5/k/vvvb5I+ZMgQnnnmmUZpo0aN4qc//SklJSV4PB5efvllpk6dCkR+aL388stcfPHFPPvss+zatavZ+gKBAOPHj2f79u3ceuutURu/+OILnnrqKZYuXUqvXr1YuHAhgwYNil5XVVXFG2+8wZ///Odomohw7rnnIiLcfPPN3HBD05UM3/72t5kwYQKjR49m/Pjx/PKXv+S1115rkm/cuHHN/tBIBG35tNqqGhSRrwALVfVBEUnYrCrbTtxMpq0bt1F6sIyc9HLaJl18qe/bjjftcZOPB2+88QZr165l3LhxhMNhAoEAffv25YILLmDbtm1897vfZfbs2cycObPFMlwuFxMnTmTx4sWEw2Fyc3Oj51avXs0111yDw+Ggd+/eTJ48mXXr1vH2229zzTXXYFkWubm5TJ8+HYj82t20aVN0rKJhefv27aNnz55N6v/Rj37Ez372M376058esw56WKDS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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "score_save_path = './IJBB/result'\n",
    "files = glob.glob(score_save_path + '/MS1MV2*.npy')  \n",
    "methods = []\n",
    "scores = []\n",
    "for file in files:\n",
    "    methods.append(Path(file).stem)\n",
    "    scores.append(np.load(file)) \n",
    "methods = np.array(methods)\n",
    "scores = dict(zip(methods,scores))\n",
    "colours = dict(zip(methods, sample_colours_from_colourmap(methods.shape[0], 'Set2')))\n",
    "#x_labels = [1/(10**x) for x in np.linspace(6, 0, 6)]\n",
    "x_labels = [10**-6, 10**-5, 10**-4,10**-3, 10**-2, 10**-1]\n",
    "tpr_fpr_table = PrettyTable(['Methods'] + map(str, x_labels))\n",
    "fig = plt.figure()\n",
    "for method in methods:\n",
    "    fpr, tpr, _ = roc_curve(label, scores[method])\n",
    "    roc_auc = auc(fpr, tpr)\n",
    "    fpr = np.flipud(fpr)\n",
    "    tpr = np.flipud(tpr) # select largest tpr at same fpr\n",
    "    plt.plot(fpr, tpr, color=colours[method], lw=1, label=('[%s (AUC = %0.4f %%)]' % (method.split('-')[-1], roc_auc*100)))\n",
    "    tpr_fpr_row = []\n",
    "    tpr_fpr_row.append(method)\n",
    "    for fpr_iter in np.arange(len(x_labels)):\n",
    "        _, min_index = min(list(zip(abs(fpr-x_labels[fpr_iter]), range(len(fpr)))))\n",
    "        tpr_fpr_row.append('%.4f' % tpr[min_index])\n",
    "    tpr_fpr_table.add_row(tpr_fpr_row)\n",
    "plt.xlim([10**-6, 0.1])\n",
    "plt.ylim([0.3, 1.0])\n",
    "plt.grid(linestyle='--', linewidth=1)\n",
    "plt.xticks(x_labels) \n",
    "plt.yticks(np.linspace(0.3, 1.0, 8, endpoint=True)) \n",
    "plt.xscale('log')\n",
    "plt.xlabel('False Positive Rate')\n",
    "plt.ylabel('True Positive Rate')\n",
    "plt.title('ROC on IJB-B')\n",
    "plt.legend(loc=\"lower right\")\n",
    "plt.show()\n",
    "#fig.savefig('IJB-B.pdf')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+-------------------------------------------+--------+--------+--------+--------+--------+--------+\n",
      "|                  Methods                  | 1e-06  | 1e-05  | 0.0001 | 0.001  |  0.01  |  0.1   |\n",
      "+-------------------------------------------+--------+--------+--------+--------+--------+--------+\n",
      "| MS1MV2-ResNet100-ArcFace-TestMode(N1D1F1) | 0.4091 | 0.9081 | 0.9477 | 0.9636 | 0.9755 | 0.9863 |\n",
      "| MS1MV2-ResNet100-ArcFace-TestMode(N0D1F2) | 0.4089 | 0.8995 | 0.9463 | 0.9642 | 0.9761 | 0.9867 |\n",
      "| MS1MV2-ResNet100-ArcFace-TestMode(N1D1F2) | 0.4281 | 0.9082 | 0.9490 | 0.9647 | 0.9767 | 0.9866 |\n",
      "| MS1MV2-ResNet100-ArcFace-TestMode(N1D0F0) | 0.3900 | 0.9042 | 0.9467 | 0.9620 | 0.9761 | 0.9860 |\n",
      "| MS1MV2-ResNet100-ArcFace-TestMode(N0D0F0) | 0.3828 | 0.8933 | 0.9425 | 0.9615 | 0.9751 | 0.9856 |\n",
      "| MS1MV2-ResNet100-ArcFace-TestMode(N1D1F0) | 0.3930 | 0.9039 | 0.9476 | 0.9630 | 0.9758 | 0.9861 |\n",
      "| MS1MV2-ResNet100-ArcFace-TestMode(N0D1F0) | 0.3892 | 0.8984 | 0.9456 | 0.9626 | 0.9753 | 0.9861 |\n",
      "+-------------------------------------------+--------+--------+--------+--------+--------+--------+\n"
     ]
    }
   ],
   "source": [
    "print(tpr_fpr_table)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# setting N1D1F2 is the best"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
